package org.reborn.engine.render.texture

import javax.media.opengl.{GL,GL2,GL2GL3,GL2ES1,GL2ES2}

object TextureFilter extends Enumeration{
  type TextureFilter = Value
  val Nearest, Linear, 
      Nearest_MipmapNearest, Nearest_MipmapLinear,
      Linear_MipmapNearest, Linear_MipmapLinear = Value
      
  val filterToGLConst = {
	var map:Map[TextureFilter,Int] = Map()
	map += (Nearest -> GL.GL_NEAREST)
	map += (Linear -> GL.GL_LINEAR)
	map += (Nearest_MipmapNearest -> GL.GL_NEAREST_MIPMAP_NEAREST)
	map += (Nearest_MipmapLinear -> GL.GL_NEAREST_MIPMAP_LINEAR)
	map += (Linear_MipmapNearest -> GL.GL_LINEAR_MIPMAP_NEAREST)
	map += (Linear_MipmapLinear -> GL.GL_LINEAR_MIPMAP_LINEAR)
	map
  }
}

object TextureWrap extends Enumeration{
  type TextureWrap = Value
  val Repeat, Clamp, Mirror_Repeat = Value
      
  val wrapToGLConst = {
	var map:Map[TextureWrap,Int] = Map()
	map += (Repeat -> GL.GL_REPEAT)
	map += (Clamp -> GL2.GL_CLAMP)
	map += (Mirror_Repeat -> GL.GL_MIRRORED_REPEAT)
	map
  }
}

import TextureFilter._
import TextureWrap._

trait TexFilter{
  self: TextureMetadata =>
  var minFilter:TextureFilter = Linear
  var magFilter:TextureFilter = Linear

  addTexParameterCommand(setUpFilter)
  
  def setUpFilter(gl:GL){
	gl.glTexParameteri(glTarget, GL.GL_TEXTURE_MIN_FILTER, filterToGLConst(minFilter))
	gl.glTexParameteri(glTarget, GL.GL_TEXTURE_MAG_FILTER, filterToGLConst(magFilter))
  }
}

trait TexWrap{
  self: TextureMetadata =>
  var repeatS:TextureWrap = Repeat
  var repeatT:TextureWrap = Repeat
  var repeatR:TextureWrap = Repeat

  addTexParameterCommand(setUpWrap)
  
  def setUpWrap(gl:GL){
	gl.glTexParameteri(glTarget, GL.GL_TEXTURE_WRAP_S, wrapToGLConst(repeatS))
	
	if(texDimensions >= 2)
	  gl.glTexParameteri(glTarget, GL.GL_TEXTURE_WRAP_T, wrapToGLConst(repeatT))
	
	if(texDimensions >= 3)
	  gl.glTexParameteri(glTarget, GL2ES2.GL_TEXTURE_WRAP_R, wrapToGLConst(repeatR))
  }
}

trait TexAutoMipMap{
  self: TextureMetadata =>
  var generateMipMaps = false

  addTexParameterCommand(setUpGenMipMaps)
  
  def setUpGenMipMaps(gl:GL){
	if(generateMipMaps){
	  gl.glTexParameteri(glTarget, GL2ES1.GL_GENERATE_MIPMAP, GL.GL_TRUE)
	}
  }
}

trait TextureMetadata{
  val texDimensions:Int
  val glTarget:Int
  protected var glIdName:Int = 0
  var glInternalFormat:Int = GL.GL_RGB
  private var glTexCommands:List[(GL)=>Unit] = Nil
  
  /**
   * Add additional commands to be executed when creating a texture
   * @param cmd a function that executes code that can use a GL object
   */
  protected def addTexParameterCommand(cmd:(GL)=>Unit):Unit = {
	glTexCommands = glTexCommands ::: List(cmd)
  }
  
  /**
   * Executes any commands that were added by metadata helpers
   * @param gl a reference to a GL object
   */
  def doTexParameterCommands(gl:GL){
	for(cmd <- glTexCommands){ 
	  cmd(gl) 
	}
  }
  
  //Setter is protected to this package
  protected[texture] def glId_=(id:Int){ glIdName = id }
  
  /**
   * @return the GL texture id/name for this texture
   */
  def glId = glIdName
}

trait BaseTextureMetadata extends TextureMetadata with TexWrap with TexFilter with TexAutoMipMap